package NF;

import java.io.*;


class Table
{
    public String name;
    public String[] pKeys;
    public String[] oCols;
    
    public Table(String Name)
    {
        name = Name;
    }
    public Table(Table _Table)
    {
        name = _Table.name;
        
        pKeys = new String[_Table.pKeys.length];
        oCols = new String[_Table.oCols.length];
        
        for(int i=0; i<pKeys.length; i++)
            pKeys[i] = _Table.pKeys[i];
        for(int i=0; i<oCols.length; i++)
            oCols[i] = _Table.oCols[i];
    }
}

public class NF 
{
    public static final int _INPUT = 0;
    public static final int _OUTPUT = 1;
    
    private static Table[] tables = new Table[10];
    private static String[][] results;
    
    public static void main (String[] args) throws IOException, Exception
    {
        // Get the args
        String[] arguments = getArgs(args);
        
        // Get the database
        try{
            Database DC = new Database();
        
            // Start the database class connection
            try{
                DC.startConnection ("config.jdbc");
            }catch(Exception e){ throw new Exception("Error parsing config file: " + e); }

            try
            {
                // Open the file reader for the input file
                BufferedReader br = new BufferedReader( 
                        new InputStreamReader( 
                        new DataInputStream( 
                        new FileInputStream(arguments[_INPUT]) 
                )));
                String strLine;

                int counter = 0;
                strLine = br.readLine(); // Read the first line
                while(strLine != null)   // Loop until EOF
                {
                    // If tables isn't big enough, double in size.
                    if(counter == tables.length)
                    {
                        Table[] temp = new Table[tables.length];
                        System.arraycopy(tables, 0, temp, 0, tables.length);
                        tables = new Table[tables.length*2];
                        System.arraycopy(temp, 0, tables, 0, temp.length);
                    }
                    
                    // Get the table name
                    tables[counter] = new Table(strLine.substring(0, strLine.indexOf('(')));

                    // This makes a string of all the keys and non-keys, stripping off the parentheses
                    strLine = strLine.substring(strLine.indexOf('(')+1,strLine.length()-1);

                    // Split all the keys and non-keys into an array
                    String[] keys = strLine.split(",");

                    // Find How many primary key candidates there are
                    int pk = 0;
                    for(int i=0; i<keys.length; i++)
                        if(keys[i].endsWith("(k)"))
                            pk++;

                    // Initialize the list of primary keys and non-key attributes to the correct length
                    tables[counter].pKeys = new String[pk];
                    tables[counter].oCols = new String[keys.length-pk];

                    // Fill the arrays with the appropriate data
                    int p=0,o=0;                    
                    for(int i=0; i<keys.length; i++)
                    {
                        if(keys[i].endsWith("(k)"))
                        {
                            tables[counter].pKeys[p] = keys[i].substring(0,keys[i].indexOf("(k)"));
                            p++;
                        }
                        else
                        {
                            tables[counter].oCols[o] = keys[i];
                            o++;
                        }
                    }   
                    
                    counter++;                      // Get next line in file
                    strLine = br.readLine();
                }

                br.close();                         // Close the reader
                results = new String[counter][2];   // Make a new results array of lenght "number of tables"
            }catch(Exception e){  System.out.println(e);  }
            
            /*
             * //This block prints out all the table data as parsed.
            for(int i=0; i<results.length; i++)
            {
                System.out.println("Table: " + tables[i].name);
                System.out.print("Candidate Keys: ");
                for(int j=0; j<tables[i].pKeys.length; j++)
                    System.out.print(tables[i].pKeys[j] + ", ");
                System.out.println();
                System.out.print("Other Columns: ");
                for(int j=0; j<tables[i].oCols.length; j++)
                    System.out.print(tables[i].oCols[j] + ", ");
                System.out.println();
                System.out.println();
            }
            * */

            // Get the results
            for(int i=0; i<results.length; i++)
                results[i] = DC.NFResult(tables[i].name, tables[i].pKeys, tables[i].oCols);

            try // Create output
            {
                PrintWriter pw = new PrintWriter(new File(arguments[_OUTPUT]));

                // Find the maximum length of a table name
                int maxLen = 0;
                for(int i=0; i<results.length; i++)
                    if(tables[i].name.length() > maxLen)
                        maxLen = tables[i].name.length();
                maxLen += 5;

                // Format the table header for output
                pw.format("%1$-" + maxLen + "s Form   Y_N   Reason\n", "Table");
                try{ DC.sendQuery ("DROP TABLE NF_team9"); }catch(Exception dropex){}
                DC.sendQuery ("CREATE TABLE NF_team9 (TableName text, Form text, Y_N text, Reason text)");
                
                // Format and write output
                for(int i=0; i<results.length; i++)
                {
                    String theName = tables[i].name;
                    int theNF;
                    
                    if(results[i][0] == null)
                        theNF = 0;
                    else
                        theNF = Integer.parseInt(results[i][0].substring(0, 1));

                    for(int j=1; j<=theNF; j++)
                    {
                        pw.format(
                            "%1$-" + maxLen + "s %2$-6s Y\n", 
                            theName, 
                            j+"NF"
                        );
                        
                        DC.sendQuery("INSERT INTO NF_team9 VALUES ('"+theName+"','"+j+"NF','Y',null)");
                    }

                    if(theNF < 3)
                    {
                        pw.format(
                                "%1$-" + maxLen + "s %2$-6s %3$-5s %4$s\n", 
                                theName, 
                                theNF+1+"NF", 
                                "N", 
                                results[i][1]
                        );
                        int thisNF = theNF+1;
                        DC.sendQuery("INSERT INTO NF_team9 VALUES ('"+theName+"','"+thisNF+"NF','N','"+results[i][1]+"')");
                    }
                }

                // Close connections
                pw.close();
                DC.stopConnection();
            }catch(Exception e){ System.out.println(e); }
        }catch(Exception e){ throw e; }
        
        
    }
    
    // This method gets the list of arguments and parses them
    static String[] getArgs(String[] Args) throws IOException
    {
        if(Args.length > 0)
        {
            
            String[] result = Args[0].split("\\;");
            
            if(result.length < 2)
                throw new IOException("Please specify input and output file.");
            
            String[] temp = result[0].split("\\=");
            
            if(temp.length < 2)
                throw new IOException("Argument string is improperly formatted.");
            
            result[_INPUT] = temp[1];
            
            temp = result[1].split("\\=");
            
            if(temp.length < 2)
                throw new IOException("Argument string is improperly formatted.");
            
            result[_OUTPUT] = temp[1];
            
            return result;
        }
        else
            throw new IOException("Please specify input and output file.");
    }
}